package com.zhang.service;

import com.alibaba.fastjson.JSON;
import com.zhang.entity.ChannelBody;
import com.zhang.handle.NettyMessageHandle;
import com.zhang.util.CommandRedisUtil;
import com.zhang.util.DeviceRedisUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * User: 张
 * Date: 2024-11-15
 * Time: 19:07
 * Description:
 */
@Component
public class IoTNettyServer {
    @Value("${netty.server.port}")
    private int port;
    private final EventLoopGroup bossGroup = new NioEventLoopGroup();
    private final EventLoopGroup workerGroup = new NioEventLoopGroup();
    private Channel serverChannel;
    private final CopyOnWriteArrayList<Channel> clients = new CopyOnWriteArrayList<>();

    @Autowired
    private NettyMessageHandle nettyMessageHandle;
    @Autowired
    private DeviceRedisUtil deviceRedisUtil;
    @Autowired
    private CommandRedisUtil commandRedisUtil;

    @PostConstruct
    public void start() throws Exception {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new IoTServerHandler());
                    }
                });
        deviceRedisUtil.initDeviceList();
        commandRedisUtil.initCommandList();

        serverChannel = b.bind(port).sync().channel();

        System.out.println("物联网Netty网络开启 端口为：" + port);
    }
    public void broadcastMessage(String message) {
        for (Channel client : clients) {
            if (client.isActive()) {
                ByteBuf byteBuf = Unpooled.copiedBuffer(message.getBytes());
                client.writeAndFlush(byteBuf);
            }
        }
    }
    public void broadcastMessage(String channelIdShortText ,String message) {
        for (Channel client : clients) {
            if (client.isActive() && client.id().asShortText().equalsIgnoreCase(channelIdShortText)) {
                ByteBuf byteBuf = Unpooled.copiedBuffer(message.getBytes());
                client.writeAndFlush(byteBuf);
            }
        }
    }
    @PreDestroy
    public void stop() throws Exception {
        serverChannel.close().sync();
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
        System.out.println("物联网Netty网络关闭");
    }
    private class IoTServerHandler extends ChannelInboundHandlerAdapter {

        @Override
        public void channelActive(ChannelHandlerContext ctx) {
            clients.add(ctx.channel());
            System.out.println("客户端上线 id为" + ctx.channel().id().asShortText() + " ip为："+ctx.channel().localAddress() +":" + ctx.channel().remoteAddress());
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            clients.remove(ctx.channel());
            System.out.println("客户端下线 id为" + ctx.channel().id().asShortText() + " ip为："+ctx.channel().localAddress());
            nettyMessageHandle.handleChannelInactive(ctx.channel().id().asShortText());
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            // 这里可以处理客户端发送的消息，例如打印或进一步处理
            if (msg instanceof ByteBuf) {
                ByteBuf buf = (ByteBuf) msg;
                // 确保ByteBuf有足够的可读字节
                if (buf.isReadable()) {
                    // 将ByteBuf转换为字符串
                    String receivedMessage = buf.toString(io.netty.util.CharsetUtil.UTF_8);
                    System.out.println("收到来自客户端 id:"+ctx.channel().id().asShortText()
                            + "ip: "+ ctx.channel().localAddress()+"的消息: " + receivedMessage);
                    nettyMessageHandle.handleMessage(receivedMessage,ctx.channel().id().asShortText());
                    // 释放ByteBuf内存
                    buf.release();
                }
            } else {
                super.channelRead(ctx, msg);
            }
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
//            cause.printStackTrace();
            System.out.println("设备异常断开 id为"+ctx.channel().id() + " ip为："+ctx.channel().localAddress());
            nettyMessageHandle.handleExceptionMessage(ctx.channel().id().asShortText());
            ctx.close();
        }
    }

}
